package com.lzq.badminton.service.impl;

import cn.hutool.core.lang.generator.SnowflakeGenerator;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzq.badminton.Exception.SystemException;
import com.lzq.badminton.dto.BookingDto;
import com.lzq.badminton.dto.OrderDto;
import com.lzq.badminton.dto.PayDto;
import com.lzq.badminton.dto.UpdateBookingDto;
import com.lzq.badminton.entity.Arena;
import com.lzq.badminton.entity.Booking;
import com.lzq.badminton.entity.Order;
import com.lzq.badminton.entity.User;
import com.lzq.badminton.enums.AppHttpCodeEnum;
import com.lzq.badminton.mapper.OrderMapper;
import com.lzq.badminton.service.ArenaService;
import com.lzq.badminton.service.BookingService;
import com.lzq.badminton.service.OrderService;
import com.lzq.badminton.service.UserService;
import com.lzq.badminton.utils.BeanCopyUtils;
import com.lzq.badminton.utils.SecurityUtils;
import com.lzq.badminton.utils.WeChatPayUtil;
import com.lzq.badminton.vo.OrderPaymentVO;
import com.lzq.badminton.vo.OrderVo;
import com.lzq.badminton.vo.ResponseResult;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RabbitListener(queues = "order.release.order.queue")
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private final SnowflakeGenerator snowflakeGenerator = new SnowflakeGenerator();

    @Autowired
    private BookingService bookingService;

    @Autowired
    private UserService userService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private WeChatPayUtil weChatPayUtil;

    @Autowired
    private ArenaService arenaService;

    @Override
    @Transactional
    public ResponseResult addOrder(OrderDto orderDto) {
        Long userId = SecurityUtils.getUserId();

        //雪花算法生成唯一订单号

        //将订单中的预定信息插入Booking表
        List<BookingDto> bookingDtoList = orderDto.getBookingDtoList();


        //计算订单所有场地的价格
        double totalAmount = 0;
        ArrayList<Long> bookingIds = new ArrayList<>();
        for(BookingDto bookingDto : bookingDtoList){
            bookingIds.add(bookingDto.getBookingId());
        }

        List<Booking> bookingList = bookingService.listByIds(bookingIds);
        LocalDateTime startTime = LocalDateTime.MAX;
        LocalDateTime endTime = LocalDateTime.MIN;

        for(Booking booking : bookingList){
            List<LocalDateTime> localDateTimes = convertBookingToDateTime(booking);
            //遍历场地找到最早时间和最晚时间
            //获取startTime
            LocalDateTime tStartTime = localDateTimes.get(0);
            if(tStartTime.isBefore(startTime)){
                startTime = tStartTime;
            }
            //获取endTime
            LocalDateTime tEndTime = localDateTimes.get(1);
            if(tEndTime.isAfter(endTime)){
                endTime = tEndTime;
            }


            totalAmount += booking.getPrice();
        }


        User user = userService.getById(userId);

        //创建订单
        Order order = new Order();
//        order.setId(orderId);
        order.setUserId(userId);
        order.setArenaId(orderDto.getArenaId());
        order.setOrderTime(LocalDateTime.now());
        order.setAmount(totalAmount);
        //支付状态设置为0
        order.setPayStatus(0);
        //设置开始时间和结束时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//        String sformat = startTime.format(formatter);
//        String eformat = endTime.format(formatter);
//        LocalDateTime ss = LocalDateTime.parse(sformat, formatter);
//        LocalDateTime ee = LocalDateTime.parse(eformat, formatter);
//        order.setStartTime(ss);
//        order.setEndTime(ee);
        order.setStartTime(startTime);
        order.setEndTime(endTime);
        save(order);
        System.out.println("增加订单的订单表的orderId:" + order.getId());
        Long orderId = order.getId();


        List<UpdateBookingDto> updateBookingDtoList = BeanCopyUtils.copyBeanList(bookingDtoList, UpdateBookingDto.class);
        updateBookingDtoList.stream().map(updateBookingDto -> {
            updateBookingDto.setOrderId(order.getId());
            System.out.println("增加订单的预定表的orderId:" + order.getId());
            updateBookingDto.setStatus(1);
            return updateBookingDto;
        }).collect(Collectors.toList());

        //查询场地状态能否预约
        //修改预定表的场地预约状态

        bookingService.orderBookings(updateBookingDtoList);


        //给死信队列发送订单的Id
        rabbitTemplate.convertAndSend("order-event-exchange", "order.create.order", orderId);

        OrderVo orderVo = BeanCopyUtils.copyBean(order, OrderVo.class);
        Arena arena = arenaService.getById(orderDto.getArenaId());
        orderVo.setArenaName(arena.getArenaName());
        orderVo.setBookingVoList(bookingService.listByOrderId(orderId));
        orderVo.setArenaImg(arena.getImg());
        orderVo.setBrief(arena.getBrief());
        return ResponseResult.okResult(orderVo);

    }

//    @Override
//    public OrderPaymentVO payOrder(PayDto payDto) throws Exception {
//        String openId = SecurityUtils.getOpenId();
//        Order order = getById(payDto.getOrderId());
//        Double amount = order.getAmount();
//        JSONObject jsonObject = weChatPayUtil.pay(
//                payDto.getOrderId().toString(),
//                new BigDecimal(amount),
//                "羽毛球场预约订单",
//                openId
//        );
//        if(jsonObject.getString("code") != null)
//            if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
//                throw new SystemException(AppHttpCodeEnum.ORDER_PAYD);
//            }
//
//        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
//        vo.setPackageStr(jsonObject.getString("package"));
//
//        return vo;
//    }

    @Override
    public OrderPaymentVO payOrder(PayDto payDto) throws Exception {
        String openId = SecurityUtils.getOpenId();
        Order order = getById(payDto.getOrderId());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "ORDERPAID");
        OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
        vo.setPackageStr(jsonObject.getString("package"));

        order.setPayTime(LocalDateTime.now());
        order.setPayStatus(1);
        updateById(order);
        return vo;
    }

    @Override
    public void paySuccess(String outTradeNo) {
        // 当前登录用户id
        Long userId = SecurityUtils.getUserId();
        // 根据订单号查询当前用户的订单
        Order order = getById(outTradeNo);
        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        order.setPayStatus(1);
        order.setPayTime(LocalDateTime.now());
        //更新订单记录
        updateById(order);

        //通过websocket向客户端浏览器推送消息 type orderId content
//        Map map = new HashMap();
//        map.put("type",1); // 1表示来单提醒 2表示客户催单
//        map.put("orderId",ordersDB.getId());
//        map.put("content","订单号：" + outTradeNo);
//
//        String json = JSON.toJSONString(map);
//        webSocketServer.sendToAllClient(json);
    }

//    @Override
//    public void userCancelById(Long id) throws Exception {
//// 根据id查询订单
//        Order order = getById(id);
//
//        // 校验订单是否存在
//        if (order == null) {
//            throw new SystemException(AppHttpCodeEnum.ORDER_NO_FOUND);
//        }
//
//        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
//        if (order.getStatus() != 1) {
//            throw new SystemException(AppHttpCodeEnum.ORDER_STATUS_ERROR);
//        }
//
//
//        //调用微信支付退款接口
//        weChatPayUtil.refund(
//            order.getId().toString(), //商户订单号
//            order.getId().toString(), //商户退款单号
//            new BigDecimal(order.getAmount()),//退款金额，单位 元
//            new BigDecimal(order.getAmount()));//原订单金额
//
//        // 更新订单状态、取消原因、取消时间
//        order.setPayStatus(2);
//        order.setCancelReason("用户退款");
//        order.setCancelTime(LocalDateTime.now());
//        updateById(order);
//    }

    @Override
    public void userCancelById(Long id) throws Exception {
// 根据id查询订单
        Order order = getById(id);

        // 校验订单是否存在
        if (order == null) {
            throw new SystemException(AppHttpCodeEnum.ORDER_NO_FOUND);
        }

        //订单状态 0为取消，1为进行中，2为已完成
        if (order.getStatus() != 1) {
            throw new SystemException(AppHttpCodeEnum.ORDER_STATUS_ERROR);
        }


//        //调用微信支付退款接口
//        weChatPayUtil.refund(
//            order.getId().toString(), //商户订单号
//            order.getId().toString(), //商户退款单号
//            new BigDecimal(order.getAmount()),//退款金额，单位 元
//            new BigDecimal(order.getAmount()));//原订单金额

        // 更新订单状态、取消原因、取消时间
        order.setPayStatus(2);
        order.setCancelReason("用户退款");
        order.setCancelTime(LocalDateTime.now());
        bookingService.clearOrderId(id);
        updateById(order);
    }

    @Override
    public List<OrderVo> listOrderByUser(Integer pageNum, Integer pageSize, Integer status) {
        //导航栏有三种状态: 待支付， 进行中， 已完成
        //对应上面的形参status: 1,2,3
        Long userId = SecurityUtils.getUserId();
        //订单:0为取消，1为进行中，2为已完成
        //支付状态: 支付状态 0未支付 1已支付 2退款
        //订单状态的更新是懒更新,也就是只有查询的时候才会更新
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getUserId, userId);
        queryWrapper.in(Order::getPayStatus, 1,2);

        queryWrapper.eq(Order::getStatus, 1);
        List<Order> orderList1 = list(queryWrapper);
        orderList1.stream()
                .map(order -> {
                    if(order.getEndTime().isBefore(LocalDateTime.now()) || order.getPayStatus() == 2){
                        //当前时间大于结束时间，或者已退款, 则状态置为已完成
                        order.setStatus(2);
                    }else{
                        order.setStatus(1);
                    }
                    return order;
                }).collect(Collectors.toList());
        //更新订单状态
        updateBatchById(orderList1);



        LambdaQueryWrapper<Order> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Order::getUserId, userId);

        if(status == 1){
            lambdaQueryWrapper.eq(Order::getPayStatus, 0);
            lambdaQueryWrapper.eq(Order::getStatus, 1);
        } else if (status == 2) {
            lambdaQueryWrapper.eq(Order::getStatus, 1);
        } else if (status == 3) {
            lambdaQueryWrapper.eq(Order::getStatus, 2);
        }
        lambdaQueryWrapper.orderByDesc(Order::getOrderTime);
        Page<Order> page = new Page<>(pageNum, pageSize);
        page(page, lambdaQueryWrapper);
        List<Order> orderList = page.getRecords();
//        List<Order> orderList = list(lambdaQueryWrapper);
        List<OrderVo> orderVoList = BeanCopyUtils.copyBeanList(orderList, OrderVo.class);
        orderVoList.stream()
                .map(orderVo -> {
                    orderVo.setBookingVoList(bookingService.listByOrderId(orderVo.getId()));
                    Arena arena = arenaService.getById(orderVo.getArenaId());
                    orderVo.setArenaName(arena.getArenaName());
                    orderVo.setBrief(arena.getBrief());
                    orderVo.setArenaImg(arena.getImg());
                    return orderVo;
                })
                .collect(Collectors.toList());

        return orderVoList;

    }

    @Override
    public void cancleNoRefund(Long id) {
        Order order = getById(id);
        order.setStatus(0);
        updateById(order);
        bookingService.clearOrderId(id);
    }

    @Override
    public int deleteRecord() {
        return baseMapper.delete(null);
    }

    //处理死信队列的订单
    @RabbitHandler
    public void handleOrderRelease(Long orderId){
        System.out.println("延时队列启动!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + orderId);
        //检查订单的支付状态
        Order order = getById(orderId);
        if(order == null){
            return;
        }
        Integer payStatus = order.getPayStatus();
        if(payStatus == 0){
            //未支付则设置订单为取消
            order.setStatus(0);
            //预约表的订单号清空
            bookingService.clearOrderId(orderId);
        }else order.setStatus(1);
        updateById(order);
    }

    public static List<LocalDateTime> convertBookingToDateTime(Booking booking) {
        if (booking == null || booking.getDate() == null || booking.getTimeSlot() == null) {
            // 处理输入为空的情况
            return null;
        }

        LocalDate date = booking.getDate();
        String timeSlot = booking.getTimeSlot();

        // 解析时间槽的开始和结束时间
        String[] timeSlotParts = timeSlot.split("-");
        if (timeSlotParts.length != 2) {
            // 处理无效的时间槽格式
            return null;
        }

        String startTimeStr = timeSlotParts[0];
        String endTimeStr = timeSlotParts[1];

        // 将日期和时间合并为 LocalDateTime
        LocalDateTime startDateTime = LocalDateTime.of(date, LocalTime.parse(startTimeStr));
        LocalDateTime endDateTime = LocalDateTime.of(date, LocalTime.parse(endTimeStr));

        // 这里可以根据实际需求选择使用 startDateTime 或 endDateTime，或者根据业务逻辑进一步处理

        List<LocalDateTime> localDateTimes = new ArrayList<>();
        localDateTimes.add(startDateTime);
        localDateTimes.add(endDateTime);
        return localDateTimes;
    }
}
